package com.earthchen.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.pagination.PageHelper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.earthchen.core.enums.ResultEnum;
import com.earthchen.core.exception.BaseException;
import com.earthchen.core.support.redis.key.shiro.ShiroKey;
import com.earthchen.core.support.redis.service.RedisService;
import com.earthchen.core.support.shiro.token.PasswordToken;
import com.earthchen.core.util.JsonWebTokenUtil;
import com.earthchen.demo.dao.SysUserDao;
import com.earthchen.demo.dao.SysUserRoleDao;
import com.earthchen.demo.domain.SysUser;
import com.earthchen.demo.domain.SysUserRole;
import com.earthchen.demo.dto.SysUserDTO;
import com.earthchen.demo.enums.ExceptionEnum;
import com.earthchen.demo.exception.AuthException;
import com.earthchen.demo.service.SysUserRoleService;
import com.earthchen.demo.service.SysUserService;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author earthchen
 * @date 2018/9/4
 **/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser>
        implements SysUserService {

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private RedisService redisService;


    @Override
    public String selectUserRoles(String appId) {
        return sysUserDao.selectUserRoles(appId);
    }

    @Override
    public String login(String appId, String password) {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new PasswordToken(appId, password));
        } catch (Exception e) {
            throw new BaseException(ResultEnum.LOGIN_AUTHENTICATION_FAIL);
        }

        // 加载当前用户的角色
        String roles = selectUserRoles(appId);
        // 时间以秒计算,token有效刷新时间是token有效过期时间的2倍
        long refreshPeriodTime = 36000L;
        String jwt = JsonWebTokenUtil.issueJWT(UUID.randomUUID().toString(), appId,
                "token-server", refreshPeriodTime >> 2, roles, null, SignatureAlgorithm.HS512);
        redisService.set(ShiroKey.getJwtSession, appId, jwt);
        return jwt;
    }

    @Override
    public SysUser register(SysUserDTO sysUserDTO) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserDTO, sysUser);
        sysUser.setStatus((byte) 1);
        boolean success = insert(sysUser);
        return success ? sysUser : null;
    }

    @Override
    public boolean authorityUserRole(long userId, long roleId) {
        SysUser sysUser = selectById(userId);
        if (sysUser == null) {
            throw new AuthException(ExceptionEnum.USERID_NOT_EXISTS);
        }
        SysUserRole sysUserRole = sysUserRoleService.selectOne(
                new EntityWrapper<SysUserRole>()
                        .where("user_id={0} and role_id={1}", userId, roleId));
        if (sysUserRole != null) {
            throw new AuthException(ExceptionEnum.USERID_ROLEID_ALREADY_EXISTS);

        }
        SysUserRole newUserRole = new SysUserRole(userId, roleId);
        return sysUserRoleService.insert(newUserRole);
    }

    @Override
    public List<SysUser> getUserListByRoleId(long roleId) {
        return sysUserDao.selectUserListByRoleId(roleId);
    }


    /**
     * 创建令牌
     *
     * @param appId
     * @param password
     * @return
     */
    private AuthenticationToken createPasswordToken(String appId, String password) {
        return new PasswordToken(appId, password);
    }


}
